import logging
import re

from datetime import datetime

from flask import render_template, jsonify, request, current_app, session, abort, make_response, g
from sqlalchemy import and_

from info import db, constants, redis_store
from info.models import User, Shop_cart
from info.utils.captcha.captcha import captcha
from info.utils.common import user_login_data
from info.utils.response_code import RET
from . import passport_blu


@passport_blu.route('/login', methods=["POST", "GET"])
def login():
    """
       1. 获取参数和判断是否有值
       2. 从数据库查询出指定的用户
       3. 校验密码
       4. 保存用户登录状态
       5. 返回结果
       :return:

    """

    if request.method == "GET":
        return render_template("index/login.html")

    params = request.json
    username = params.get('username')
    password = params.get('password')

    # 2. 校验参数
    if not username:
        return jsonify(errno=RET.PARAMERR, errmsg="请输入用户名")

    if not password:
        return jsonify(errno=RET.PARAMERR, errmsg="请输入密码")

    # 3. 校验密码是否正确
    # 先查询出当前是否有指定手机号的用户
    try:
        user = User.query.filter(User.user_id == username).first()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="用户不存在")
    # 判断用户是否存在
    if not user:
        return jsonify(errno=RET.NODATA, errmsg="用户名或密码错误")

    # 校验登录的密码和当前用户的密码是否一致
    if not user.check_password(password):
        return jsonify(errno=RET.PWDERR, errmsg="用户名或者密码错误")

    # # 校验登录的密码和当前用户的密码是否一致
    # if not user.check_password(password):
    #     return jsonify(errno=RET.PWDERR, errmsg="用户名或者密码错误")

    # 4. 保存用户的登录状态
    session["user_id"] = user.user_id
    session["nick_name"] = user.nick_name

    # 设置当前用户最后一次登录的时间
    user.last_login = datetime.now()
    user.user_stutas = 1
    try:
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='登录失败!')

    # 5返回相应
    return jsonify(errno=RET.OK, errmsg='登录成功')


@passport_blu.route('/yzzc', methods=["POST", 'GET'])
def yyzc():
    """
        注册的逻辑
        1. 获取参数
        2. 校验参数
        3. 从redis的真实的短信验证码内容
        4. 校验用户输入的短信验证码内容和真实验证码内容是否一致
        5. 如果一致，初始化 User 模型，并且赋值属性添加数据库
        6. 保存用户登录状态
        7. 返回响应
        :return:
        """
    if request.method == 'GET':
        return render_template('index/register.html')
    elif request.method == 'POST':
        # 1. 获取参数
        param_dict = request.json
        # 用户名
        username = param_dict.get("username")
        # print(username)
        # 密码
        password_1 = param_dict.get("password_1")
        # 确认密码
        password_2 = param_dict.get("password_2")
        # 手机号
        mobile = param_dict.get("phone")
        # 验证码
        image_code = param_dict.get("yzm")
        image_code_id = param_dict.get('image_code_id')
        # 2. 校验参数
        if not all([username, password_1, password_2, image_code]):
            return jsonify(errno=RET.PARAMERR, errmsg="请填写完整信息")

        if len(username) < 6:
            return jsonify(errno=RET.PARAMERR, errmsg='用户名不能小于6位数')

        if len(password_1) < 6:
            return jsonify(errno=RET.PARAMERR, errmsg='密码不能小于6位数')

        # 判断密码是否相同
        if password_1 != password_2:
            return jsonify(errno=RET.PWDERR, errmsg="密码不一致")

        # 3 从reids获取真是的验证码 和 接受的验证码对比
        try:
            real_image_code = redis_store.get('ImageCode_' + image_code_id)
        except Exception as e:
            # logging.error(e)
            current_app.logger.error(e)
            ret = {'errno': RET.DBERR, 'errmsg': '数据查询失败'}
            return jsonify(ret)

        if not real_image_code:
            # 数据不存在 过期了
            ret = {'errno': RET.NODATA, 'errmsg': '图片验证码已过期'}
            return jsonify(ret)

            # 4 对比如果不一致  返回错误信息
        if real_image_code.upper() != image_code.upper():
            ret = {'errno': RET.DATAERR, 'errmsg': '验证码输入错误'}
            return jsonify(ret)

        user = User.query.filter(User.user_id == username).first()

        if user:
            return jsonify(errno=RET.PARAMERR, errmsg="用户名已存在")
        # 校验手机号是否正确
        if not re.match('1[35678]\\d{9}', mobile):
            return jsonify(errno=RET.PARAMERR, errmsg="手机号格式不正确")

        # 5. 如果一致，初始化 User 模型，并且赋值属性添加数据库
        user = User()
        user.user_id = username
        # 记录用户最后一次登录时间
        user.last_login = datetime.now()  # 最后登录时间
        # 对密码做处理
        # 需求：在设置 password 的时候，去对 password 进行加密，并且将加密结果给 user.password_hash 赋值
        user.password = password_1  # 密码
        user.mobile = mobile  # 手机
        user.rg_time = datetime.now()  # 注册时间

        # 5.1 添加到数据库
        try:
            db.session.add(user)
            db.session.commit()
        except Exception as e:
            current_app.logger.error(e)
            db.session.rollback()
            return jsonify(errno=RET.DBERR, errmsg="数据保存失败")

        # shop_car = Shop_cart()
        # shop_car.c_user_id = user.u_id
        # try:
        #     db.session.add(shop_car)
        # except Exception as e:
        #     current_app.logger.error(e)
        #     db.session.rollback()
        #     return jsonify(errno=RET.DBERR, errmsg="数据保存失败")
        # print(shop_car.c_user_id)
        #  6. 保存用户登录状态
        session["user_id"] = user.user_id  # 用户名
        session["nick_name"] = user.nick_name  # 昵称
        session["rg_time"] = user.rg_time  # 注册时间

        # 7. 返回响应
        return jsonify(errno=RET.OK, errmsg="注册成功")


@passport_blu.route('/image_code')
def get_image_code():
    """
    获取图片验证码
    :return:
    """

    # 1. 获取到当前的图片编号id
    code_id = request.args.get('code_id')
    if not code_id:
        logging.error('没有传入code_id')
        abort(404)

    # 2. 生成验证码
    name, text, image = captcha.generate_captcha()
    try:
        # 保存当前生成的图片验证码内容
        redis_store.setex('ImageCode_' + code_id, constants.IMAGE_CODE_REDIS_EXPIRES, text)
    except Exception as e:
        logging.error(e)
        abort(500)

    # 返回响应内容
    response = make_response(image)
    # 设置内容类型
    response.headers['Content-Type'] = 'image/jpg'
    return response


# 退出
@passport_blu.route("/logout", methods=['POST'])
@user_login_data
def logout():
    """
    清除session中的对应登录之后保存的信息
    :return:
    """

    user = g.user
    user.user_stutas = 0
    try:
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg='退出失败')
    # pop返回 删除的值  如果不存在 就返回None
    session.pop('user_id', None)
    session.pop('nick_name', None)

    # 返回结果
    return jsonify(errno=RET.OK, errmsg="OK")


@passport_blu.route('/new_password', methods=["GET", "POST"])
@user_login_data
def new_password():
    user = g.user
    if request.method == 'GET':
        if not user:
            return render_template('common/404.html')
        data = {
            'user_info': user
        }
        return render_template('index/Wopop.html', data=data)
    # 1. 获取到传入参数
    data_dict = request.json
    old_password = data_dict.get("old_password")
    new_password = data_dict.get("new_password")

    if not all([old_password, new_password]):
        return jsonify(errno=RET.PARAMERR, errmsg="参数有误")

    # 2. 获取当前登录用户的信息
    user = g.user

    if not user.check_password(old_password):
        return jsonify(errno=RET.PWDERR, errmsg="原密码错误")

    # 更新数据
    user.password = new_password
    try:
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg="保存数据失败")

    return jsonify(errno=RET.OK, errmsg="保存成功")
